<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vue面试题</title>
    <link rel="stylesheet" href="../1style/index.css"/>
    <script src="../1style/jquery.js"></script>
</head>
<body>
<h1>Vue面试题</h1>
http://www.zhufengpeixun.cn/train/
https://blog.csdn.net/qq_42755530/article/details/107177248
<h3><span>命中</span>Vue生命周期</h3>
<div>
    <pre>
      Vue生命周期
      https://upload-images.jianshu.io/upload_images/13119812-5890a846b6efa045.png
      props => methods =>data => computed => watch; 懂了没
      组件生命周期钩子
      beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed
      https://www.bilibili.com/video/BV1y741137Xr
      https://www.bilibili.com/video/BV1fV41127uL // 55分 20200903_202056-珠峰-最火Vue面试题训练营
    </pre>
</div>

<h3><span>命中</span>Vue自定义指令</h3>
<div>
    <pre>
      https://www.cnblogs.com/greatdesert/p/11171785.html
      https://www.cnblogs.com/greatdesert/category/1481032.html?page=2
      https://segmentfault.com/a/1190000022877076
      Vue.directive(指令名，配置参数)注册>自定义指令可以绑定如下钩子函数:
    ·bind		只调用一次，元素渲染成DOM节点后
    ·inserted	被绑定元素插入父节点时调用 (仅保证父节点存在，但不一定已被插入文档中)。
    ·update		所在组件的 VNode 更新时调用，但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变，也可能没有。
    ·componentUpdated 	指令所在组件的 VNode 及其子 VNode 全部更新后调用。
    ·unbind				只调用一次，指令与元素解绑时调用。
      每钩子函数有四个参数
        el(对应的DOM节点引用)
        binding(一些关于指令的扩展信息，是个对象)
        vnode(该节点对应的虚拟VN哦的)
        oldVnode(之前的VNode,仅在update和componentUpdated钩子中可用)
      bind钩子函数执行的时候该DOM元素被渲染出来了，但是并没有插入到父元素中
    </pre>
</div>

<h3>Vue小技巧,说说看</h3>
<div>
    <pre>
        存一份defaultData方便直接初始化
        特别是带表单的弹窗也写在一起没有生命周期的时候。
        this.$options.data().formData
    </pre>
</div>

<h3>其实vue的性能本身就是很good了，要说再进一步优化，</h3>
<div>
    <pre>
    1、不要在模板里面写过多表达式
    2、循环调用子组件时添加 key, v-for同级别v-if 的优化
    3、善用v-show，v-if 的使用
    6、慎用deep watch
    7、vue-router路由懒加载
    9、按需加载、善于运用事件代理
    0、vue中使用keep-alive
    https://www.bilibili.com/video/BV1Af4y147Da
    </pre>
</div>

<h3>你有对 Vue 项目进行哪些优化？</h3>
<div>
    <pre>
    （1）代码层面的优化
        v-if 和 v-show 区分使用场景
        computed 和 watch 区分使用场景
        v-for 遍历必须为 item 添加 key，且避免同时使用 v-if
        长列表性能优化,事件的销毁,图片资源懒加载,路由懒加载,第三方插件的按需引入
        优化无限列表性能,服务端渲染 SSR or 预渲染
    （2）Webpack 层面的优化
        Webpack 对图片进行压缩,提取公共代码,
        减少 ES6 转为 ES5 的冗余代码,
        模板预编译,提取组件的 CSS,优化 SourceMap,
        构建结果输出分析,Vue 项目的编译优化,
    （3）基础的 Web 技术的优化
        开启 gzip 压缩,浏览器缓存,CDN 的使用,使用 Chrome Performance 查找性能瓶颈
    </pre>
</div>

<h3>computed 和 watch 区分使用场景</h3>
<div>
    <pre>
    共同点:值发生改变都会去更新视图
    watch 要和data同名,computed 需要不同名,要return
    computed 不能发送api请求,computed 可以缓存数据
    </pre>
</div>

<h3>你知道v-model的原理吗？说说看</h3>
<div>
    <pre>
    v-model只是语法糖而已
    核心:input v-bind:value="sth" v-on:input="sth = $event.target.value" />
    简写:input :value="sth" @input="sth = $event.target.value" /> @input-->html5新的事件类似 onchange ，每当输入框内容发生变化时，就会触发oninput，把最新的value传递给 sth。
    </pre>
</div>

<h3>VUE响应式原理</h3>
<div>
    <pre>
      在initData的时候传入组件vm,检测data props // src\core\instance\state.js
      后observe函数进行数据对象defineProperty代理,数组会重写方法,
      get进行dep数组添加Watcher依赖收集,set时候会subs[i].update()更新
      def函数加上__ob__属性(dep{id,subs},value,vmCount)
    </pre>
</div>

<h3><span>命中</span>Vue的$set是怎么实现的</h3>
<div>
    <pre>
        1.如果数据是普通类型,不可以进行set
        2.如果数组的话 用的改写后的 array.splice 进行替换
        2.如果对象的话 defineProperty进行处理
        3.const ob = (target: any).__ob__ // 判断目标值是否为响应式的
        4.代理这个值 5 更新dom 6.return vue
        set以后这个值就变成响应式的了
    </pre>
</div>

<h3>VUE数组怎么监听的--7数组常用函数重新监控</h3>
<div>
    <pre>
        push pop shift unshift splice sort reverse
    </pre>
</div>

<h3>VUE异步编程</h3>
<div>
    <pre>
      当数据变化后会调用notify方法，将watcher遍历，调用update方法通知watcher进行更新，
      这时候watcher并不会立即去执行，在update中会调用queueWatcher方法将watcher放到了一个队列里，
      在queueWatcher会根据watcher的进行去重，多个属性依赖一个watcher，
      如果队列中没有该watcher就会将该watcher添加到队列中，然后通过nextTick异步执行flushSchedulerQueue方法刷新watcher队列。
      flushSchedulerQueue中开始会触发一个before的方法，其实就是beforeUpdate，然后watcher.run() 才开始真正执行watcher，
      执行完页面就渲染完成啦，更新完成后会调用updated钩子
    </pre>
</div>

<h3>#nextTick</h3>
<div>
    <pre>
        只要观察到数据变化，Vue 将开启一个队列，并缓冲在同一事件循环中发生的所有数据改变。
        如果同一个 watcher 被多次触发，只会被推入到队列中一次。
        这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。
        然后，在下一个的事件循环“tick”中，Vue 刷新队列并执行实际 (已去重的) 工作。
        Vue 在内部尝试对异步队列使用原生的 Promise.then 和MessageChannel，如果执行环境不支持，
        会采用 setTimeout(fn, 0)代替。
    </pre>
</div>

<h3>怎么给vue定义全局的方法</h3>
<div>
    <pre>
    第一种：挂载到Vue的prototype上  第二种：利用全局混入mixin
    this.$root.$on  // 创建全局方法
    </pre>
</div>

<h3>怎么给vue组件之间的通信,$Bus的原理</h3>
<div>
    <pre>
    第一种：挂载到Vue的prototype上  第二种：利用全局混入mixin
    this.$root.$on  // 创建全局方法
    </pre>
</div>

<h3>vue样式穿透</h3>
<div>
    <pre>
    /deep/ 和>>>
    </pre>
</div>

<h3>vue引入img</h3>
<div>
    <pre>
        require("@/"+urlTemp)
    </pre>
</div>

<h3>vue组件中的data为啥是一个函数,而vue的根实例却没有这个限制</h3>
<div>
    <pre>
        vue\src\core\instance\state.js  initState函数
        组件是多个的:让组件独立维护自己的数据,所以用函数独立运行返回一个新的数据
        new vue的根是单个的 所有不需要有这个限制
        https://www.bilibili.com/video/BV127411P7zi?p=2
    </pre>
</div>

<h3>vue为什么要求组件模板只能有一个根元素</h3>
<div>
    <pre>
    1.每个vue文件其实都是一个vue实例,都应该有el元素
    2.虚拟DOM的根
    </pre>
</div>

<h3>keep-alive的生命周期</h3>
<div>
    <pre>
    1.activated： 页面第一次进入的时候，钩子触发的顺序是created->mounted->activated
    2.deactivated: 页面退出的时候会触发deactivated，当再次前进或者后退的时候只触发activated
    </pre>
</div>

<h3>你知道vue2.0兼容IE哪个版本以上吗</h3>
<div>
    <pre>
    不兼容ie8及以下
    是因为vue的响应式原理是基于es5的Object.defineProperty的,而这个方法不支持ie8及以下
    </pre>
</div>

<h3>你知道vue3.0/4.0双向绑定的原理么</h3>
<div>
    <pre>
    要从2个层面分析,数据变化视图变化,视图变化数据变化
    数据劫持 观察者模式 1对多的模式
    </pre>
</div>

<h3><span>命中</span>你知道vue-router的原理</h3>
<div>
    <pre>
        https://www.bilibili.com/video/BV1RK4y1r7up
        1.host模式has模式
        2.this.$router.push === window.host.pushstate
        3.has 就是#锚点
    </pre>
</div>

<h3>vue-router钩子函数有哪些？都有哪些参数？</h3>
<div>
    <pre>
    beforeEach,afterEach
    beforeEach主要有三个参数，to,form,next
    </pre>
</div>

<h3>怎样动态加载路由</h3>
<div>
    <pre>
    router.addRoutes
    </pre>
</div>

<h3>你知道style加scoped属性的用途和原理吗</h3>
<div>
    <pre>
    防止CSS样式全局污染
    属性会自动添加一个唯一的属性 (比如 data-v-21e5b78) 为组件内 CSS 指定作用域
    </pre>
</div>

<h3><span>命中</span>vue-cli3与vue-cli4的区别</h3>
<div>
    <pre>
        @vue/cli-plugin-pwa、@vue/cli-service等包的增强
        原来在根目录下的vuex.js、route.js被分别放到了对应的文件夹下
    </pre>
</div>

<h3>vue2-3的区别</h3>
<div>
    <pre>
      1.Object.defineProperty的第一个缺陷,无法监听数组变化
      但是vue中是可以监听数组的变化的，那他是怎么实现的呢？
      其实更改了数组八种方法 push() pop() shift() unshift()splice()sort()reverse()
      2.Object.defineProperty只能劫持对象的属性，从而需要对每个对象，每个属性进行遍历
      如果，属性值是对象，还需要深度遍历。
      Proxy 可以劫持整个对象，并返回一个新的对象。
      Proxy 不仅可以代理对象，还可以代理数组。还可以代理动态增加的属性。
      Proxy IE系列都不兼容Proxy
    </pre>
</div>

<h3>vue3.0有什么功能或者改进的地方</h3>
<div>
    <pre>
    TypeScript支持,https://www.bilibili.com/video/BV1V7411N7sF
        目前，Vue 的反应系统是使用 Object.defineProperty 的 getter 和 setter。
        但是，Vue 3 将使用 ES2015 Proxy 作为其观察者机制。使速度加倍，并节省了一半的内存开销。
        更快了 虚拟Dom重写  优化slots的生成 静态树提升 静态属性提升 基于Proxy的响应式系统
        更小 摇数优化
        更容易维护 TS+模块化
    </pre>
</div>

<h3>在vue事件中传入$event，使用e.target和e.currentTarget有什么区别？</h3>
<div>
    <pre>
    <span>在vue事件中传入$event</span>
    currentTarget：事件绑定的元素
    target:鼠标触发的元素
    </pre>
</div>

<h3>在.vue文件中style是必须的吗？那script是必须的吗？为什么？</h3>
<div>
    <pre>
        都不是必须的
    </pre>
</div>

<h3> vue怎么实现强制刷新组件？ </h3>
<div>
    <pre>
    强制重新渲染:::this.$forceUpdate()
    强制重新刷新某组件:: :key v-if
    </pre>
</div>

<h3>vue给组件绑定自定义事件无效怎么解决</h3>
<div>
    <pre>
    1、组件外部加修饰符.navtive
    2、组件内部声明$emit('自定义事件')
    </pre>
</div>

<h3>vue的属性名称与method的方法名称一样时会发生什么问题</h3>
<div>
    <pre>
    项目可以运行,报warn警告
    键名优先级：props > data > methods
    </pre>
</div>

<h3>v-once指令怎么用的</h3>
<div>
    <pre>
    只渲染元素和组件一次, 这可以用优化更新性能. 执行一次性地插值，当数据改变时，插值处的内容不会更新。
    </pre>
</div>

<h3>说说你对vue的修饰符</h3>
<div>
    <pre>
    事件修饰符.stop .prevent .capture .self .once .passive
    表单修饰符.number .lazy .trim .sync
    </pre>
</div>

<h3>说说你对Object.defineProperty的理解</h3>
<div>
    <pre>
    vue的数据劫持有两个缺点:
    1、无法监听通过索引修改数组的值的变化
    2、无法监听object也就是对象的值的变化
    所以vue2.x中才会有$set属性的存在
    proxy是es6中推出的新api，可以弥补以上两个缺点，所以vue3.x版本用proxy替换object.defineProperty
    </pre>
</div>

<h3>组件中写name选项有什么作用</h3>
<div>
    <pre>
    vue-devtools调试工具里显示的组见名称是由vue中组件name决定的
    项目使用keep-alive时，可搭配组件name进行缓存过滤
    </pre>
</div>

<h3>vue如何优化首页的加载速度</h3>
<div>
    <pre>
    异步路由和异步加载
    还有分屏加载, 按需加载, 延时加载图片等, cdn, 域名
    不要什么东西动不动就打包到vendor中
    </pre>
</div>

<h3>ajax、fetch、axios 这三都有什么区别</h3>
<div>
    <pre>
    ajax: 基于原生的XHR开发,嵌套回调，难以处理
    fetch:函数就是原生js，没有使用XMLHttpRequest对象。天生支持 await 默认不会带cookie|对400，500都当做成功的请求
    axios 是一个基于Promise,本质上也是对原生XHR的封装
    </pre>
</div>

<h3>使用Promise封装fetch实现网络超时，终止请求的功能</h3>
<div>
    <pre>
      https://www.jianshu.com/p/d66421c826ae
    </pre>
</div>

<h3>说说你对单向数据流和双向数据绑定的理解</h3>
<div>
    <pre>
    数据流，表明的是数据流向，用大白话说就是数据传递。
    单项数据流:父子 prop 之间形成了一个单向下行绑
    </pre>
</div>

<h3>v-if和v-for的优先级是什么？如果这两个同时出现时，那应该怎么优化才能得到更好的性能？</h3>
<div>
    <pre>
    显然v-for优先于v-if被解析。vue\src\compiler\codegen\index.js 60行左右
    每次渲染都会先执行循环再判断条件，无论如何循环都不可避免，浪费了性能。
    要避免出现这种情况，则在外层嵌套template，在这一层进行v-if判断，然后在内部进行v-for循环。
    如果判断条件出现在循环内部，用 计算属性 提前过滤掉, js的运算要比渲染页面快。
    </pre>
</div>

<h3>如何获取路由传过来的参数？</h3>
<div>
    <pre>
    如果使用query方式传入的参数使用this.$route.query 接收
    如果使用params方式传入的参数使用this.$router.params接收
    </pre>
</div>

<h3>怎么实现路由懒加载呢</h3>
<div>
    <pre>
        https://www.jianshu.com/p/876e1b85adb6
    </pre>
</div>

<h3>vuex中actions和mutations有什么区别</h3>
<div>
    <pre>
    mutations可以直接修改state，但只能包含同步操作，同时，只能在actions中通过提交commit调用
    actions是用来触发mutations的，它无法直接改变state，它可以包含异步操作，它只能通过store.dispatch触发
    </pre>
</div>

<h3>vuex的state、getter、mutation、action、module特性分别是什么</h3>
<div>
    <pre>
    state, 状态初始化, 并实施观察
    getter, 获取数据用于view或data中使用
    mutation: 内部处理state变化
    action: 处理外部交互
    module: 模块化以上四个
    </pre>
</div>

<h3><span>命中</span>你有二次封装过ElementUI组件吗</h3>
<div>
    <pre>
        类似于分页, 表格, 毕竟每个项目的这些东西
    </pre>
</div>

<h3><span>命中</span>组件封装遇到的问题,解决方案</h3>
<div>
    <pre>
      1.为什么要这样做？  2.做了哪些工作？   3.解决了哪些痛点？  4.取得了哪些效果？  5.过程中遇到了哪些难点？   6.怎么突破的？适合各类问题~~
      个人认为功能独立、出现次数频繁，那么就可以抽出来做成组件了
      不不不，面试官只是想知道你封装组件的思想。公用和灵活性到什么程度，并且了解各种传参，更新双向绑定方式,组件尽量是干净的,不产生副作用
      为了组件的更好的通用性,预留solt钩子
    </pre>
</div>
<h3>vue异步组件</h3>
<div>
    <pre>
    </pre>
</div>
<h3>vue插槽和作用域插槽</h3>
<div>
    <pre>
    </pre>
</div>

<h3>说说你对 SPA 单页面的理解，它的优缺点分别是什么？</h3>
<div>
    <pre>
    优点：
        用户体验好、快，内容的改变不需要重新加载整个页面，避免了不必要的跳转和重复渲染；
        基于上面一点，SPA 相对对服务器压力小；
        前后端职责分离，架构清晰，前端进行交互逻辑，后端负责数据处理；
    缺点：
        初次加载耗时多：为实现单页 Web 应用功能及显示效果，需要在加载页面的时候将 JavaScript、CSS 统一加载，部分页面按需加载；
        前进后退路由管理：由于单页应用在一个页面中显示所有的内容，所以不能使用浏览器的前进后退功能，所有的页面切换需要自己建立堆栈管理；
        SEO 难度较大：由于所有的内容都在一个页面中动态替换显示，所以在 SEO 上其有着天然的弱势。
    </pre>
</div>


</body>
</html>

<script>
  $(function () {
    $("h3").click(function () {
      $(this).next().toggle();
    });
  })
</script>

